package controllers

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"github.com/beego/beego/v2/server/web"
)

type OssController struct {
	web.Controller
}

// S3配置信息
var accessKeyId string = "fnyfi2f368pbic74d8ll"
var accessKeySecret string = "jgqwk7sirqlz2602x2k7yx2eor0vii19wah6ywlv"
var bucket string = "gdsc-ai-aqzs"
var endpoint string = "172.16.17.52:8060"
var region string = "raoxi" // S3区域，可根据实际情况调整

// S3服务地址 - 标准S3格式
var host string = "http://" + endpoint + "/" + bucket

// 用户上传文件时指定的前缀
var upload_dir string = "uploads/"
var expire_time int64 = 1800 // 30分钟

// S3策略文档结构
type S3PolicyDocument struct {
	Expiration string        `json:"expiration"`
	Conditions []interface{} `json:"conditions"`
}

// S3响应结构
type S3PolicyToken struct {
	URL        string            `json:"url"`
	Fields     map[string]string `json:"fields"`
	Expire     int64             `json:"expire"`
	StatusCode int               `json:"statusCode"`
}

// 生成AWS4签名
func generateAWS4Signature(secretKey, dateStamp, region, stringToSign string) string {
	kDate := hmacSHA256([]byte("AWS4"+secretKey), dateStamp)
	kRegion := hmacSHA256(kDate, region)
	kService := hmacSHA256(kRegion, "s3")
	kSigning := hmacSHA256(kService, "aws4_request")
	signature := hmacSHA256(kSigning, stringToSign)
	return hex.EncodeToString(signature)
}

// HMAC-SHA256计算
func hmacSHA256(key []byte, data string) []byte {
	mac := hmac.New(sha256.New, key)
	mac.Write([]byte(data))
	return mac.Sum(nil)
}

func (c *OssController) Upload() {
	// 设置CORS头
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "Content-Type")

	// 处理OPTIONS预检请求
	if c.Ctx.Request.Method == "OPTIONS" {
		c.Ctx.ResponseWriter.WriteHeader(200)
		return
	}

	// 临时设置user_id，实际应该从token中获取
	user_id := 1

	// 生成时间相关字符串
	now := time.Now().UTC()
	expire_end := now.Unix() + expire_time
	dateStamp := now.Format("20060102")
	amzDate := now.Format("20060102T150405Z")
	expiration := now.Add(time.Duration(expire_time) * time.Second).Format("2006-01-02T15:04:05.000Z")
	
	// 生成credential
	credential := fmt.Sprintf("%s/%s/%s/s3/aws4_request", accessKeyId, dateStamp, region)

	// 生成上传目录
	uploadDir := upload_dir + now.Format("01") + now.Format("02") + "/" + strconv.Itoa(user_id) + "/"

	// 创建S3策略文档
	policy := S3PolicyDocument{
		Expiration: expiration,
		Conditions: []interface{}{
			map[string]string{"bucket": bucket},
			[]interface{}{"starts-with", "$key", uploadDir},
			map[string]string{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
			map[string]string{"x-amz-credential": credential},
			map[string]string{"x-amz-date": amzDate},
			[]interface{}{"content-length-range", "0", "104857600"}, // 最大100MB
		},
	}

	// 将策略文档转换为JSON并进行Base64编码
	policyJSON, err := json.Marshal(policy)
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"error":      "Failed to create policy",
		}
		c.ServeJSON()
		return
	}

	policyBase64 := base64.StdEncoding.EncodeToString(policyJSON)

	// 生成AWS4签名
	signature := generateAWS4Signature(accessKeySecret, dateStamp, region, policyBase64)

	// 构建表单字段
	fields := map[string]string{
		"key":                   uploadDir + "${filename}",
		"policy":                policyBase64,
		"x-amz-algorithm":       "AWS4-HMAC-SHA256",
		"x-amz-credential":      credential,
		"x-amz-date":           amzDate,
		"x-amz-signature":      signature,
	}

	// 构建响应
	var policyToken S3PolicyToken
	policyToken.StatusCode = 200
	policyToken.URL = host
	policyToken.Fields = fields
	policyToken.Expire = expire_end

	c.Data["json"] = policyToken
	c.ServeJSON()
}
